package wkt.auth;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import net.xnzn.framework.config.exception.BizRuntimeException;
import net.xnzn.framework.secure.filter.before.security.SmUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import wkt.WebUtils;
import wkt.basic.Basic;
import wkt.basic.BasicExamDate;
import wkt.basic.BasicExamDateMapper;
import wkt.basic.BasicMapper;
import wkt.student.Student;
import wkt.student.StudentMapper;
import wx.Code;
import wx.Code2Session;
import wx.api.Code2SessionService;
import wx.ex.AcquireCode2SessionException;

import javax.validation.Valid;
import java.util.List;
import java.util.SortedMap;

@Slf4j
@RestController
@RequestMapping("/mini-app/auth")
public class MiniAppUserController {
    @Autowired
    StudentMapper studentMapper;
    @Autowired
    Code2SessionService code2SessionService;
    @Autowired
    BasicExamDateMapper basicExamDateMapper;
    @Autowired
    BasicMapper basicMapper;

    @PostMapping("/login/password")
    @Transactional(rollbackFor = Exception.class)
    public Student loginWithPassword(@Valid @RequestBody MiniAppLogin miniAppLogin) {
        final Student student = studentMapper.selectOne(Wrappers.lambdaQuery(Student.class)
                .select(Student::getId, Student::getName, Student::getMobile, Student::getAccount, Student::getPassword, Student::getExamDateId, Student::getOpenId, Student::getUsedTimeSecond,Student::isRemoveOnAnswerRight)
                .eq(Student::getAccount, miniAppLogin.getUsername())
                .eq(Student::getState, "NORMAL"));
        if (student == null) throw new BizRuntimeException("用户名/密码错误");

        SortedMap<String, String> data = Maps.newTreeMap();
        data.put("password", miniAppLogin.getPassword());
        if (!student.getPassword().equals(SmUtils.signBySm3WithServerKey(data, "clientKey"))) {
            throw new BizRuntimeException("用户名/密码错误");
        }

        studentMapper.update(null, Wrappers.lambdaUpdate(Student.class)
                .set(Student::getOpenId, null)
                .eq(Student::getOpenId, student.getOpenId()));

        studentMapper.update(null, Wrappers.lambdaUpdate(Student.class)
                .set(Student::getOpenId, miniAppLogin.getOpenId())
                .eq(Student::getId, student.getId()));
        return completeInfo(student);
    }

    @PostMapping("/login/code")
    public Student loginWithCode(@Valid @RequestBody Code code) throws AcquireCode2SessionException {
        Code2Session code2Session = code2SessionService.getCode2Session(code.getCode());
        final String openid = code2Session.getOpenid();

        Student student = completeInfo(studentMapper.selectOne(Wrappers.lambdaQuery(Student.class)
                .select(Student::getId, Student::getName, Student::getMobile, Student::getAccount, Student::getExamDateId, Student::getOpenId, Student::getUsedTimeSecond,Student::isRemoveOnAnswerRight)
                .eq(Student::getOpenId, openid)
                .eq(Student::getState, "NORMAL")));
        if (student == null) student = new Student();
        student.setOpenId(openid);
        return student;
    }

    @PostMapping("/logout")
    public void logout() {
        if (WebUtils.studentId() == null) return;
        studentMapper.update(null,
                Wrappers.lambdaUpdate(Student.class)
                        .eq(Student::getId, WebUtils.studentId())
                        .set(Student::getOpenId, null)
        );
    }


    public Student completeInfo(Student student) {
        if (student == null) return null;

        BasicExamDate basicExamDates = basicExamDateMapper.selectOne(Wrappers.lambdaQuery(BasicExamDate.class)
                .select(BasicExamDate::getId, BasicExamDate::getBasicId, BasicExamDate::getDate)
                .eq(BasicExamDate::getId, student.getExamDateId()));
        student.setExamDate(basicExamDates);

        Basic zhuanye = basicMapper.selectOne(Wrappers.lambdaQuery(Basic.class)
                .select(Basic::getId, Basic::getName, Basic::getCode, Basic::getType, Basic::getParentId)
                .eq(Basic::getId, basicExamDates.getBasicId()));
        student.setZhuanye(zhuanye);

        List<Basic> kemu = basicMapper.selectList(Wrappers.lambdaQuery(Basic.class)
                .select(Basic::getId, Basic::getName, Basic::getCode, Basic::getType, Basic::getParentId)
                .eq(Basic::getParentId, zhuanye.getId()));
        student.setKemu(kemu);

        Basic cenci = basicMapper.selectOne(Wrappers.lambdaQuery(Basic.class)
                .select(Basic::getId, Basic::getName, Basic::getCode, Basic::getType, Basic::getParentId)
                .eq(Basic::getId, zhuanye.getParentId()));
        student.setCenci(cenci);
        return student;
    }
}
